#include "CategoryView.h"

#include <QVBoxLayout>
#include <QPushButton>
#include <QInputDialog>

#include <QDebug>

#include "WPData.h"
#include "ScopedTimer.h"

#include "utils.h"
#include "inputdialog.h"

CategoryView::CategoryView (QWidget *parent) : 
    QFrame(parent),
    iTreeWidget(NULL),
    iCurrentBlog(NULL)
{
    // XXX: title for BlogView
    setWindowTitle(tr("Categories"));

    // layout
    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->setSpacing(0);
    layout->setContentsMargins(0, 0, 0, 0);

    setLayout(layout);

    // setup tree view for touch selection
    iTreeWidget = new QTreeWidget(this);
    iTreeWidget->setColumnCount(1);
    iTreeWidget->setHeaderHidden(true);
    iTreeWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
    iTreeWidget->setSelectionMode(QAbstractItemView::MultiSelection);
    iTreeWidget->setSortingEnabled(false);
    iTreeWidget->setAllColumnsShowFocus(false); // XXX: true -> focus doesn't show up
    
    iTreeWidget->setRootIsDecorated(false);
    iTreeWidget->setItemsExpandable(true);
    iTreeWidget->setAnimated(true);
    
    // XXX move to theme data
    // should be set in QSS, but can't. image + padding
    if(Utils::smallScreen()) {
        iTreeWidget->setIndentation(20 /* px */);
    }else {
        iTreeWidget->setIndentation(50 /* px */);
    }
    

    // button
    QPushButton* addCategoryButton = new QPushButton(tr("Add new category..."), this);
    connect(addCategoryButton, SIGNAL(clicked()), this, SLOT(AddCategoryClicked()));

    layout->addWidget(iTreeWidget);
    layout->addWidget(addCategoryButton);

//#ifdef Q_OS_SYMBIAN
    // Prepare softkeys
    QAction* leftSoftKey = new QAction(tr("Select"), this);
    connect(leftSoftKey, SIGNAL(triggered()), this, SLOT(SaveClicked()));
    leftSoftKey->setSoftKeyRole(QAction::PositiveSoftKey);

    QAction* rightSoftKey = new QAction(tr("Cancel"), this);
    connect(rightSoftKey, SIGNAL(triggered()), this, SLOT(CancelClicked()));
    rightSoftKey->setSoftKeyRole(QAction::NegativeSoftKey);
//#endif

    // XXX: WPCustomViewBasicData
    iTitleText = tr("Select Category");
    iTabText = tr("Edit");
    iHappyAction = leftSoftKey;
    iSadAction = rightSoftKey;
}

CategoryView::~CategoryView()
{

}
    
QTreeWidgetItem * CategoryView::InsertCategoryItem (const WPDataCategory *category)
{
    // construct widget item for category
    QTreeWidgetItem *item = new QTreeWidgetItem();

    item->setText(0, category->iCategoryName);

    // map from categoryId
    iItems.insert(category->iCategoryId, item);

    // lookup parent
    QTreeWidgetItem *parentItem = NULL;
   
    if (!category->iParentId.isEmpty() && category->iParentId != "0") {
        parentItem = iItems.value(category->iParentId);

        if (!parentItem)
            // missing parent for item
            qWarning() << "CategoryView::InsertCategoryItem: missing parent for" << category->iCategoryId << "->" << category->iParentId;
    }

    if (parentItem) {
        // child item
        parentItem->addChild(item);

    } else {
        // top-level item
        iTreeWidget->addTopLevelItem(item);
        iTreeWidget->expandItem(item);
    }

    // ok
    return item;
}
    
void CategoryView::UpdateCategoryData (const WPDataBlog &blog)
{
    // warn if slow, using default threshold
    TIME_FUNCTION

    /* Reset tree */
    
    // we build new QTreeWidgetItem's each time
    iItems.clear();

    // this clears our selections, but currently we don't care, and we can restore those if needed
    iTreeWidget->clear();

    /* Build new tree */

    // the iCategories list is guaranteed to be sorted in such an order that an items parent comes
    // before the (child) item itself, so this greatly simplifies our operation here, as we can do
    // this in a single pass
    for (QListIterator<WPDataCategory> i(blog.iCategories); i.hasNext(); ) {
        const WPDataCategory &category = i.next();

        // insert into tree
        InsertCategoryItem(&category);
    }

    // XXX: maintain signals
    if (iCurrentBlog != &blog) {
        if (iCurrentBlog)
            disconnect(iCurrentBlog, NULL, this, NULL);

        // XXX: remember for SelectCategories
        // XXX: yay const
        iCurrentBlog = const_cast<WPDataBlog *>(&blog);

        connect(
            iCurrentBlog,   SIGNAL(CategoryAdded (WPDataCategory *)),
            this,             SLOT(CategoryAdded (WPDataCategory *))
        );
    }

    // XXX: show all items?
    // iTreeWidget->expandAll();
}
    
void CategoryView::CategoryAdded (WPDataCategory *category)
{
    // insert into tree
    QTreeWidgetItem *item = InsertCategoryItem(category);

    // select it
    item->setSelected(true);

    // make sure it's expanded
    iTreeWidget->expandItem(item);

    // scroll to it
    iTreeWidget->scrollToItem(item);
}

void CategoryView::SelectCategories (const QList<const WPDataCategory *> &categories)
{
    // forget old selection
    iTreeWidget->clearSelection();

    // apply new selection
    for (QListIterator<const WPDataCategory *> i(categories); i.hasNext(); ) {
        const WPDataCategory *category = i.next();
        QTreeWidgetItem *item;

        // find item
        if ((item = iItems.value(category->iCategoryId)) == NULL) {
            // faail
            qWarning() << "CategoryView::SelectCategories: missing item for" << category->iCategoryId;

            break;
        }

        // select
        item->setSelected(true);
    }
}
    
void CategoryView::SelectCategories (const QStringList &categoryNames)
{
    // look up WPDataCategory for each name
    QList<const WPDataCategory *> categories;

    if (!iCurrentBlog) {
        qWarning() << "CategoryView::SelectCategories: no iCurrentBlog";

        return;
    }

    // build list
    for (QStringListIterator i(categoryNames); i.hasNext(); ) {
        const QString &categoryName = i.next();

        // XXX: argh!
        for (QListIterator<WPDataCategory> j(iCurrentBlog->iCategories); j.hasNext(); ) {
            const WPDataCategory &category = j.next();

            if (category.iCategoryName.compare(categoryName) == 0) {
                // found
                categories.append(&category);

                break;
            }
        }
    }

    // process
    SelectCategories(categories);
}

void CategoryView::setFocus ()
{
    // XXX: unused
}

void CategoryView::SaveClicked ()
{
    QStringList categoryNames;

    // collect list of selected categories and emit signal
    for (QListIterator<QTreeWidgetItem *> i(iTreeWidget->selectedItems()); i.hasNext(); ) {
        QTreeWidgetItem *item = i.next();

        // XXX: just use raw category name from ui widget
        categoryNames.append(item->text(0));
    }

    // signal
    emit SelectionDone(categoryNames);
}

void CategoryView::CancelClicked ()
{
    // just leave current state hanging around...
    emit SelectionCancelled();
}

void CategoryView::AddCategoryClicked ()
{
#if 0 // QInputDialog is broken on symbian full screen :(
    bool ok;

    // prompt
    QString categoryName = QInputDialog::getText(this,
             tr("New Category"),
             tr("Category name:"),
             QLineEdit::Normal, QString(), 
             &ok
    );

    if (ok && !categoryName.isEmpty() && iCurrentBlog) {
        // add it, we can handle the CategoryAdded() later without losing our current selection
        iCurrentBlog->AddCategory(categoryName);
    }
#else
    
    InputDialog dlg(tr("New category"), tr("Category name:"), tr("Category"), this);
    connect(&dlg, SIGNAL(textComplete(const QString&)), this, SLOT(AddCategory(const QString&)));
    dlg.exec();
    
#endif
}

void CategoryView::AddCategory(QString const & name) {
    if (!name.isEmpty() && iCurrentBlog) {
        // add it, we can handle the CategoryAdded() later without losing our current selection
        iCurrentBlog->AddCategory(name);
    }
}
